package emulator.shell.GUI.menu;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.SwingConstants;
import javax.swing.GroupLayout.Alignment;
import javax.swing.GroupLayout.Group;
import javax.swing.GroupLayout.ParallelGroup;
import javax.swing.GroupLayout.SequentialGroup;

import emulator.hardware.bus.Bus;
import emulator.hardware.bus.VicBus;
import emulator.shell.GUI.windows.ManagedWindow;
import emulator.shell.GUI.windows.WindowManager;

public class WindowConfiguration implements ActionListener {
	private static final int BLOCK_BUTTON_FACTOR = 10;
	private int window_id;
	private WindowManager window_manager;
	private VicBus bus;
	
	private JRadioButton[] empty_checks = new JRadioButton[5];
	private JRadioButton[] rom_checks = new JRadioButton[5];
	private JRadioButton[] ram_checks = new JRadioButton[5];
	
	public WindowConfiguration(WindowManager window_manager, int window_id, Bus bus)
	{
		this.window_manager = window_manager;
		this.window_id = window_id;
		this.bus = (VicBus)bus;
	}

	@Override
	public void actionPerformed(ActionEvent arg0)
	{
		if (window_manager.isWindowActive(window_id))
			closeWindow();
		else
			openWindow();
	}

	private void openWindow() {
		ManagedWindow window = window_manager.createWindow(window_id, "Configuration");
		initDialog(window);
		initButtonStates();
		window.restorePosition();
		window.setVisible(true);
	}

	private void closeWindow() {
		window_manager.closeWindow(window_id);
	}

	private void initDialog(ManagedWindow window) {
		JLabel label_title = new JLabel("Memory configuration");
		
		JLabel label_empty = new JLabel("Empty");
		JLabel label_rom = new JLabel("ROM");
		JLabel label_ram = new JLabel("RAM");
		
		JLabel[] labels = new JLabel[] {
			new JLabel("3k: 0400-0FFF"),
			new JLabel("8k: 2000-3FFF"),
			new JLabel("8k: 4000-5FFF"),
			new JLabel("8k: 6000-7FFF"),
			new JLabel("8k: A000-BFFF") };

		for (int i = 0; i < 5; i++)
		{
			empty_checks[i] = new JRadioButton();
			empty_checks[i].setActionCommand(new Integer(i*BLOCK_BUTTON_FACTOR).toString());
			empty_checks[i].addActionListener(new RadioButtonListener());
			rom_checks[i] = new JRadioButton();
			rom_checks[i].setActionCommand(new Integer(i*BLOCK_BUTTON_FACTOR+1).toString());
			rom_checks[i].addActionListener(new RadioButtonListener());
			ram_checks[i] = new JRadioButton();
			ram_checks[i].setActionCommand(new Integer(i*BLOCK_BUTTON_FACTOR+2).toString());
			ram_checks[i].addActionListener(new RadioButtonListener());
			ButtonGroup button_group = new ButtonGroup();
			button_group.add(empty_checks[i]);
			button_group.add(rom_checks[i]);
			button_group.add(ram_checks[i]);
		}
		
		Container panel = window.getContentPane();
		GroupLayout layout = new GroupLayout(panel);
		panel.setLayout(layout);
		
		layout.setAutoCreateGaps(true);
		layout.setAutoCreateContainerGaps(true);
		
		layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING)
			.addComponent(label_title)
			.addGroup(layout.createSequentialGroup()
				.addGroup(createLabelColumn(labels, layout))
				.addGroup(createButtonColumn(label_empty, empty_checks, layout))
				.addGroup(createButtonColumn(label_rom, rom_checks, layout))
				.addGroup(createButtonColumn(label_ram, ram_checks, layout))
			)
		);
		SequentialGroup vertical_group = layout.createSequentialGroup()
			.addComponent(label_title)
			.addGroup(layout.createParallelGroup()
				.addComponent(label_empty)
				.addComponent(label_rom)
				.addComponent(label_ram)
			);
		for (int i = 0; i < labels.length; i++)
			vertical_group.addGroup(createMemoryRow(i, labels[i], layout));
		layout.setVerticalGroup(vertical_group);
		
	    layout.linkSize(SwingConstants.HORIZONTAL, label_empty, label_rom, label_ram);
	}

	private Group createMemoryRow(int i, JLabel label, GroupLayout layout) {
		ParallelGroup group = layout.createParallelGroup(Alignment.LEADING);
		group.addComponent(label);
		group.addComponent(empty_checks[i]);
		group.addComponent(rom_checks[i]);
		group.addComponent(ram_checks[i]);
		return group;
	}

	private Group createLabelColumn(JLabel[] labels, GroupLayout layout) {
		ParallelGroup group = layout.createParallelGroup(Alignment.LEADING);
		for (int i = 0; i < labels.length; i++)
			group.addComponent(labels[i]);
		return group;
	}

	private Group createButtonColumn(JLabel label, JRadioButton[] boxes, GroupLayout layout) {
		ParallelGroup group = layout.createParallelGroup(Alignment.LEADING);
		group.addComponent(label);
		for (int i = 0; i < boxes.length; i++)
			group.addComponent(boxes[i]);
		return group;
	}

	private void initButtonStates() {
		initButtons(0, bus.getBlock3k());
		initButtons(1, bus.getBlock0());
		initButtons(2, bus.getBlock1());
		initButtons(3, bus.getBlock2());
		initButtons(4, bus.getBlock3());
	}

	private void initButtons(int i, int block_state) {
		switch(block_state)
		{
		case VicBus.EMPTY_BLOCK:
			empty_checks[i].setSelected(true);
			break;
		case VicBus.ROM_BLOCK:
			rom_checks[i].setSelected(true);
			break;
		case VicBus.RAM_BLOCK:
			ram_checks[i].setSelected(true);
			break;
		}
	}

	class RadioButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			int hint = Integer.decode(e.getActionCommand());
			int block_no = hint / BLOCK_BUTTON_FACTOR;
			int block_state = hint % BLOCK_BUTTON_FACTOR;
			switch (block_no)
			{
			case 0: bus.setBlock3k(block_state); break;
			case 1: bus.setBlock0(block_state); break;
			case 2: bus.setBlock1(block_state); break;
			case 3: bus.setBlock2(block_state); break;
			case 4: bus.setBlock3(block_state); break;
			}
		}
	}
}
